<style lang="scss" scoped>
.xjw-sticky {
  .xjw-sticky {
    &--fixed {
      position: fixed;
      width: 100%;
      left: 0;
      z-index: 3000;
    }
  }
}
</style>
<template>
  <view class="">
    <view
      class="xjw-sticky"
      :class="[guidClass]"
      :style="{
        height: isFixed ? Rect.height + 'px' : 'auto',
      }"
    >
      <view
        :class="{ '.xjw-sticky--fixed': isFixed }"
        :style="{
          top: gapTop + 'px',
        }"
        ><slot></slot>
      </view>
    </view>
  </view>
</template>

<script lang="ts">
import Vue from "vue";
import { Component, Prop, Watch } from "vue-property-decorator";
import { guid } from "../lib/utils/utils";
import { getRect } from "../lib/function/index";

@Component
export default class Index extends Vue {
  @Prop({ type: Number, default: 0 }) gapTop;
  @Prop({ type: Boolean, default: false }) switch;

  guidClass: string = guid();

  Rect = {
    height: "auto",
    top: 0,
  };

  observerClear: Function | null = null;

  isFixed: boolean = false;

  @Watch("gapTop")
  WatchGap() {
    this.initObserver();
  }
  @Watch("switch")
  WatchSwitch(value) {
    if (value === false) {
      this.isFixed = false;
      this.clearObserver();
    } else {
      this.initObserver();
    }
  }

  mounted() {
    this.initObserver();
  }

  initObserver() {
    if (!this.switch) return;

    getRect(this, "." + this.guidClass).then((e) => {
      this.Rect.top = e.top;
      this.Rect.height = e.height;
      this.$nextTick(() => {
        this.createObserver();
      });
    });
  }

  createObserver() {
    this.clearObserver();
    const observer = uni.createIntersectionObserver(this, {
      thresholds: [0.95, 0.98, 1],
    });

    observer.relativeToViewport({
      top: -this.gapTop,
    });

    observer.observe("." + this.guidClass, (res) => {
      if (!this.switch) return;
      this.setIsFixed(res.boundingClientRect.top);
    });

    this.observerClear = observer.disconnect.bind(observer);

    // this.$on("hook:beforeDestroy", () => {
    //   observer.disconnect();
    // });
  }

  clearObserver() {
    if (this.observerClear) {
      this.observerClear();
    }
  }

  setIsFixed(top: number) {
    const fixed = top < this.gapTop;
    if (fixed) this.$emit("fixed");
    else if (this.isFixed) this.$emit("unfixed");
    this.isFixed = fixed;
  }
}
</script>
